#pragma once

//#include "vector3.h"
#include <assert.h>

template <typename T> 
class Vector3;

template <typename T>
class Matrix4x4
{
	public:
		Matrix4x4(void);
		Matrix4x4(const Matrix4x4 &src);
		Matrix4x4(const T m[4][4]);
		Matrix4x4(	T m00,T m01,T m02,T m03,
					T m10,T m11,T m12,T m13,
					T m20,T m21,T m22,T m23,
					T m30,T m31,T m32,T m33);
		~Matrix4x4();

		Matrix4x4&	operator=(const Matrix4x4 &src);
		inline T 	operator()(unsigned int row,unsigned int col) const;
		inline T*	operator[](unsigned int row) const;
		Matrix4x4	transpose()const;
		Matrix4x4&	setToIdentity();

		Matrix4x4&	operator+=(const Matrix4x4 &right);
		Matrix4x4	operator+(const Matrix4x4& right) const;
		Matrix4x4&	operator-=(const Matrix4x4& right);
		Matrix4x4	operator-(const Matrix4x4& right) const;
		Matrix4x4&	operator*=(const Matrix4x4& right);
		Matrix4x4	operator*(const Matrix4x4& right) const;

		Matrix4x4&	operator*=(const float right);
		Matrix4x4	operator*(const float right)const;

		bool operator==(const Matrix4x4& right) const;
		bool operator!=(const Matrix4x4& right) const;

	private:
		//variable
		T matrixData[4][4];


	public:
		//class functions
		static Matrix4x4<T> Scale(Vector3<T> v);
		//static Matrix4x4 SQT(Vector3<T> s,);
};

typedef Matrix4x4<float> Matrix4x4f;
typedef Matrix4x4<double> Matrix4x4d;

//template <typename T>
//Matrix4x4<T> Scale(Vector3<T> v)
//{
//	return new Matrix4x4<T>();
//}

template<typename T>
inline T Matrix4x4<T>::operator()(unsigned int row,unsigned int col) const
{
	assert(row >=0 && row < 4 && col >=0 col < 4);

	return matrixData[row][col];
}



//---------------------------
template <typename T>
Matrix4x4<T>::Matrix4x4(void)
{
}

//-----------------------------------
template <typename T>
Matrix4x4<T>::Matrix4x4(const Matrix4x4 &src)
{

}

//-----------------------------------
template <typename T>
Matrix4x4<T>::Matrix4x4(const T m[4][4])
{

}

//----------------------------------
template <typename T>
Matrix4x4<T>::Matrix4x4(T m00,T m01,T m02,T m03,
	T m10,T m11,T m12,T m13,
	T m20,T m21,T m22,T m23,
	T m30,T m31,T m32,T m33)
{

}

//---------------------------------
template <typename T>
Matrix4x4<T>::~Matrix4x4()
{

}
template <typename T>
inline T*	Matrix4x4<T>::operator[](unsigned int row) const
{
	return (T*)matrixData[row];
}

template <typename T>
Matrix4x4<T>& Matrix4x4<T>::operator=(const Matrix4x4 &src)
{
	for (int i=0; i<4;++i)
	{
		for (int j=0; j<4; ++j)
		{
			this->matrixData[i][j] = src[i][j];
		}
	}
	return *this;
}